package com.hmy.contract.service.contract.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hmy.ccp.error.exception.HMYRuntimeException;
import com.hmy.ccp.starter.web.utils.UserContextUtil;
import com.hmy.contract.bo.request.contract.AreaManagerApprovalSupplyContractRequest;
import com.hmy.contract.bo.request.contract.RiskMinisterApprovalSupplyContractRequest;
import com.hmy.contract.bo.request.contract.SupplyContractApprovalHistoryRequest;
import com.hmy.contract.bo.response.contract.AreaManagerApprovalSupplyContractResponse;
import com.hmy.contract.bo.response.contract.RiskMinisterApprovalSupplyContractResponse;
import com.hmy.contract.bo.response.contract.SupplyContractApprovalHistoryResponse;
import com.hmy.contract.commons.enums.ContractStatusEnum;
import com.hmy.contract.commons.enums.ContractTypeEnum;
import com.hmy.contract.dal.mapper.ContractMapper;
import com.hmy.contract.dal.mapper.SupplyContractMapper;
import com.hmy.contract.dal.po.ContractPo;
import com.hmy.contract.dal.po.SupplyContractPo;
import com.hmy.contract.manager.order.SupplyOrderFeignClientManager;
import com.hmy.contract.manager.worklfow.FlowProcessClientManager;
import com.hmy.contract.manager.worklfow.FlowTaskClientManager;
import com.hmy.contract.service.contract.ISupplyContractApprovalService;
import com.hmy.order.api.bo.request.SupplyOrderSignContractRequest;
import com.hmy.workflow.api.bo.request.process.StartProcessInstanceRequest;
import com.hmy.workflow.api.bo.request.task.ApprovalTaskRequest;
import com.hmy.workflow.api.bo.request.task.QueryNextActiveTaskRequest;
import com.hmy.workflow.api.bo.response.process.StartProcessInstanceResponse;
import com.hmy.workflow.api.bo.response.task.ApprovalTaskResponse;
import com.hmy.workflow.api.enums.ApprovalStatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * @author seven.qi 齐胜南
 * @version 1.0
 * @description
 * @date 2024/3/13 15:07
 */
@Service
@Slf4j
public class SupplyContractApprovalServiceImpl implements ISupplyContractApprovalService {

    @Value("${process.definition.supply.contract.id}")
    private String processDefinitionId;

    @Resource
    private SupplyContractMapper supplyContractMapper;

    @Resource
    private FlowProcessClientManager flowProcessClient;

    @Resource
    private FlowTaskClientManager flowTaskClient;

    @Resource
    private ContractMapper contractMapper;

    @Resource
    private SupplyOrderFeignClientManager supplyOrderFeignClientManager;


    @Override
    public SupplyContractApprovalHistoryResponse getSupplyContractApprovalHistory(SupplyContractApprovalHistoryRequest supplyContractApprovalHistoryRequest) {
        return null;
    }

    @Override
    @Transactional
    public RiskMinisterApprovalSupplyContractResponse riskMinisterApprovalSupplyContract(RiskMinisterApprovalSupplyContractRequest riskManagerApproveRequest) {
        log.info("riskMinisterApprovalSupplyContract request:{}", riskManagerApproveRequest);
        SupplyContractPo supplyContract = querySupplyContractPo(riskManagerApproveRequest.getSupplyContractId());
        SupplyContractPo supplyContractUpdate = createSupplyContractPo(supplyContract);
        supplyContractUpdate.setApprovalComment(riskManagerApproveRequest.getComment());

        ApprovalTaskRequest approveRequest = new ApprovalTaskRequest();
        approveRequest.setProcessInstanceId(supplyContract.getProcessId());
        approveRequest.setTaskId(riskManagerApproveRequest.getTaskId());
        if (StringUtils.isBlank(riskManagerApproveRequest.getTaskId())) {
            approveRequest.setTaskId(queryNextTask(supplyContract.getProcessId()));
        }
        approveRequest.setComment(riskManagerApproveRequest.getComment());
        approveRequest.setApprovalStatus(riskManagerApproveRequest.getPass() ? ApprovalStatusEnum.PASS.getCode() : ApprovalStatusEnum.REJECT.getCode());
        Map<String, Object> variables = new HashMap<>();
        approveRequest.setVariables(variables);
        if (riskManagerApproveRequest.getPass()) {
            variables.put("riskManagerApproveResult", "agree");
            variables.put("businessStatus", ContractStatusEnum.APPROVED.getStatus());
            variables.put("businessStatusAlias", ContractStatusEnum.APPROVED.getStatusDesc());

            supplyContractUpdate.setStatus(ContractStatusEnum.APPROVED.getStatus());

            updateContractInfo(supplyContract.getContractId());
        } else {
            variables.put("riskManagerApproveResult", "reject");
            variables.put("rejectCount", 1);
            variables.put("businessStatus", ContractStatusEnum.REJECT.getStatus());
            variables.put("businessStatusAlias", ContractStatusEnum.REJECT.getStatusDesc());

            supplyContractUpdate.setStatus(ContractStatusEnum.REJECT.getStatus());
        }
        supplyContractMapper.updateById(supplyContractUpdate);

        if (!flowTaskClient.complete(approveRequest).getSuccess()) {
            throw new HMYRuntimeException(502000006);
        }
        updateSupplyOrderStatus(supplyContract.getSupplyOrderId());

        RiskMinisterApprovalSupplyContractResponse response = new RiskMinisterApprovalSupplyContractResponse();
        response.setSuccess(true);
        return response;
    }

    @Override
    @Transactional
    public AreaManagerApprovalSupplyContractResponse areaManagerApprovalContract(AreaManagerApprovalSupplyContractRequest areaManagerApproveRequest) {
        log.info("areaManagerApprovalContract request:{}", areaManagerApproveRequest);
        SupplyContractPo supplyContract =
                querySupplyContractPo(areaManagerApproveRequest.getSupplyContractId());
        SupplyContractPo supplyContractUpdate = createSupplyContractPo(supplyContract);
        supplyContractUpdate.setApprovalComment(areaManagerApproveRequest.getComment());

        ApprovalTaskRequest approveRequest = new ApprovalTaskRequest();
        approveRequest.setProcessInstanceId(supplyContract.getProcessId());
        approveRequest.setTaskId(areaManagerApproveRequest.getTaskId());
        if (StringUtils.isBlank(areaManagerApproveRequest.getTaskId())) {
            approveRequest.setTaskId(queryNextTask(supplyContract.getProcessId()));
        }
        approveRequest.setComment(areaManagerApproveRequest.getComment());
        approveRequest.setApprovalStatus(areaManagerApproveRequest.getPass() ? ApprovalStatusEnum.PASS.getCode() : ApprovalStatusEnum.REJECT.getCode());
        Map<String, Object> variables = new HashMap<>();
        approveRequest.setVariables(variables);
        if (areaManagerApproveRequest.getPass()) {
            variables.put("areaManagerApproveResult", "agree");
            variables.put("businessStatus", ContractStatusEnum.RISK_MINISTER_APPROVAL.getStatus());
            variables.put("businessStatusAlias", ContractStatusEnum.RISK_MINISTER_APPROVAL.getStatusDesc());
            supplyContractUpdate.setStatus(ContractStatusEnum.RISK_MINISTER_APPROVAL.getStatus());
        } else {
            variables.put("areaManagerApproveResult", "reject");
            variables.put("rejectCount", 1);
            variables.put("businessStatus", ContractStatusEnum.REJECT.getStatus());
            variables.put("businessStatusAlias", ContractStatusEnum.REJECT.getStatusDesc());

            supplyContractUpdate.setStatus(ContractStatusEnum.REJECT.getStatus());
        }
        supplyContractMapper.updateById(supplyContractUpdate);

        if (!flowTaskClient.complete(approveRequest).getSuccess()) {
            throw new HMYRuntimeException(502000006);
        }

        AreaManagerApprovalSupplyContractResponse response = new AreaManagerApprovalSupplyContractResponse();
        response.setSuccess(true);
        return response;
    }


    /**
     * 撤回或者驳回，之后重新提交
     *
     * @param supplyContractPo 增补合同信息
     */
    public ApprovalTaskResponse reSubmit(SupplyContractPo supplyContractPo) {
        ApprovalTaskRequest approveRequest = new ApprovalTaskRequest();
        approveRequest.setProcessInstanceId(supplyContractPo.getProcessId());
        String taskId = this.queryNextTask(supplyContractPo.getProcessId());
        approveRequest.setTaskId(taskId);
        approveRequest.setApprovalStatus(ApprovalStatusEnum.RESUBMIT.getCode());
        approveRequest.setComment("重新提交");
        Map<String, Object> variables = new HashMap<>();
        variables.put("areaManagerApproveResult", "agree");
        variables.put("businessStatus", ContractStatusEnum.WAITING_APPROVAL.getStatus());
        variables.put("businessStatusDesc",
                ContractStatusEnum.getDescByStatus(ContractStatusEnum.WAITING_APPROVAL.getStatus()));
        variables.put("taskName", ContractStatusEnum.getDescByStatus(ContractStatusEnum.WAITING_APPROVAL.getStatus()));
        approveRequest.setVariables(variables);
        ApprovalTaskResponse response = flowTaskClient.complete(approveRequest);
        if (!response.getSuccess()) {
            throw new HMYRuntimeException(502000005);
        }
        return response;
    }


    /**
     * 查询增补合同信息
     *
     * @param supplyContractId 增补合同id
     * @return 增补合同信息
     */
    private SupplyContractPo querySupplyContractPo(Long supplyContractId) {
        SupplyContractPo supplyContract =
                supplyContractMapper.selectOne(Wrappers.lambdaQuery(SupplyContractPo.class)
                        .eq(SupplyContractPo::getIsDeleted, false)
                        .eq(SupplyContractPo::getSupplyContractId, supplyContractId));
        if (supplyContract == null) {
            throw new HMYRuntimeException(502000035);
        }
        return supplyContract;
    }

    /**
     * 创建SupplyContractPo对象
     *
     * @param supplyContract 原对象
     * @return 新对象
     */
    private SupplyContractPo createSupplyContractPo(SupplyContractPo supplyContract) {
        SupplyContractPo newSupplyContract = new SupplyContractPo();
        newSupplyContract.setSupplyContractId(supplyContract.getSupplyContractId());
        UserContextUtil.initUpdaterInfo(newSupplyContract);
        newSupplyContract.setUpdateTime(LocalDateTime.now());
        return newSupplyContract;
    }

    /**
     * 给区域经理发起审批
     *
     * @param supplyContract 增补合同信息
     */
    @Override
    public StartProcessInstanceResponse startApprove(SupplyContractPo supplyContract) {
        StartProcessInstanceRequest approveReq = new StartProcessInstanceRequest();
        approveReq.setUserId(UserContextUtil.getCurrentUserId());
        approveReq.setProcessDefinitionId(processDefinitionId);
        Map<String, Object> params = BeanUtil.beanToMap(supplyContract);
        params.put("rejectCount", "0");
        params.put("deptId", UserContextUtil.getCurrentUserDefaultDeptId());
        params.put("modifyType", "增补合同");
        params.put("businessStatus", ContractStatusEnum.WAITING_APPROVAL.getStatus());
        params.put("businessStatusDesc",
                ContractStatusEnum.getDescByStatus(ContractStatusEnum.WAITING_APPROVAL.getStatus()));
        params.put("taskName", ContractStatusEnum.getDescByStatus(ContractStatusEnum.WAITING_APPROVAL.getStatus()));
        params.put("contractTypeDesc", ContractTypeEnum.getDescByType(supplyContract.getContractType()));
        approveReq.setProcessVariables(params);
        return flowProcessClient.start(approveReq);
    }


    /**
     * 查询下一个任务节点的id
     *
     * @param processInstanceId 流程实例id
     * @return taskId 个节点的任务id
     */
    private String queryNextTask(String processInstanceId) {
        QueryNextActiveTaskRequest request = new QueryNextActiveTaskRequest();
        request.setProcessInstanceId(processInstanceId);
        return flowTaskClient.queryNextActiveTask(request);
    }


    /**
     * 更新主合同是否含增补合同
     *
     * @param contractId 合同id
     */
    private void updateContractInfo(Long contractId) {
        ContractPo contractPo = new ContractPo();
        contractPo.setContractId(contractId);
        contractPo.setHasSupply(1);
        contractPo.setUpdaterId(UserContextUtil.getCurrentUserId());
        contractPo.setUpdaterName(UserContextUtil.getCurrentUserName());
        contractPo.setUpdateTime(LocalDateTime.now());
        contractMapper.updateById(contractPo);
    }


    /**
     * 更新增补订单状态为已签署
     *
     * @param supplyOrderId 增补订单id
     */
    private void updateSupplyOrderStatus(Long supplyOrderId) {
        SupplyOrderSignContractRequest request = new SupplyOrderSignContractRequest();
        request.setSupplyOrderId(supplyOrderId);
        try {
            log.info("updateSupplyOrderStatus {}", request);
            supplyOrderFeignClientManager.supplyOrderSignContract(request);
        } catch (Throwable throwable) {
            log.error("updateSupplyOrderStatus exception", throwable);
        }
    }
}
